/*	--- 中介 ---


#	用一个【中介对象】来封装【一系列的对象交互】。

【中介者】使【各个对象】不需要【显式地相互引用】，从而使其【耦合松散】，而且可以【独立地改变它们之间的交互】。

================================================================


【中介模式】（Mediator）又称【调停者模式】

【它的目的】是把【多方会谈】变成【双方会谈】，从而实现【多方的松耦合】。

有些童鞋听到【中介】立刻想到【房产中介】，立刻气不打一处来。

这个【中介模式】与【房产中介】还真有点【像】，所以消消气，先看例子。

考虑一个简单的【点餐输入】：
------------------------------
	O 汉堡
	O 鸡块
	O 薯条
	O 咖啡

	选择全部  取消所有  反选
------------------------------

这个小系统有4个参与对象：

	· 多选框
	· “选择全部”按钮
	· “取消所有”按钮
	· “反选”按钮


它的【复杂性】在于，当【多选框】变化时，它会影响【“选择全部”和“取消所有”按钮的状态】（是否可点击），当用户点击【某个按钮】时，例如“反选”，除了会影响【多选框的状态】，它又可能影响【“选择全部”和“取消所有”按钮的状态】。


所以这是一个【多方会谈】，逻辑写起来很复杂： 

	┌─────────────────┐     ┌─────────────────┐
	│  CheckBox List  │<───>│SelectAll Button │
	└─────────────────┘     └─────────────────┘
	         ▲ ▲                     ▲
	         │ └─────────────────────┤
	         ▼                       │
	┌─────────────────┐     ┌────────┴────────┐
	│SelectNone Button│<────│ Inverse Button  │
	└─────────────────┘     └─────────────────┘


如果我们引入一个【中介】，把【多方会谈】变成【多个双方会谈】，虽然【多了一个对象】，但【对象之间的关系】就变简单了：

	            ┌─────────────────┐
	     ┌─────>│  CheckBox List  │
	     │      └─────────────────┘
	     │      ┌─────────────────┐
	     │ ┌───>│SelectAll Button │
	     ▼ ▼    └─────────────────┘
	┌─────────┐
	│Mediator │
	└─────────┘
	     ▲ ▲    ┌─────────────────┐
	     │ └───>│SelectNone Button│
	     │      └─────────────────┘
	     │      ┌─────────────────┐
	     └─────>│ Inverse Button  │
	            └─────────────────┘


下面我们用【中介模式】来实现【各个UI组件的交互】。

首先把【UI组件】给【画出来】： */
public class Main {
	public static void main(String[] args) {
		new OrderFrame("Hanburger", "Nugget", "Chip", "Coffee");
	}
}

// 订单框架 OrderFrame
class OrderFrame extends JFrame {

	// Init
	public OrderFrame(String... names) {
		// 设置 Titile、Size、默认关闭等 属性
		setTitle("Order");
		setSize(460, 200);
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

		// 获取ContentPane + 自定义布局
		Container c = getContentPane(); // Pane n. 窗格
			// ContentPane() 内容窗格
		c.setLayout(new FlowLayout(FlowLayout.LEADING, 20, 20));
			// Layout n. 布局,布置
			// FlowLayout 布局管理器,布局
		c.add(new JLabel("Use Mediator Pattern"));

		// 添加布局中的UI元素
		List<JCheckBox> checkboxList = addCheckBox(names);
			// CheckBox 复选框
		JButton selectAll = addButton("Select All");
		JButton selectNone = addButton("Select None");
			selectNone.setEnabled(false);
		JButton selectInverse = addButton("Inverse Select"); // 选反
		
		new Mediator(checkBoxList, selectAll, selectNone, selectInverse);
			// Mediator 调解人,中介

		setVisible(true); // 设置可见
	}

	private JButton addButton(String label) {
		JButton button = new JButton(label);
		getContentPane().add(button);

		return button;
	}

	private List<JCheckBox> addCheckBox(String... names) {
		JPanel panel = new JPanel(); // Panel n. 面板,装饰片
		panel.add(new JLabel("Menu:"));

		List<JCheckBox> list = new ArrayList<>();

		for (String name : names) {
			JCheckBox checkbox = new JCheckBox(name);
			list.add(checkbox); // List<JCheckBox>.add()
			panel.add(checkbox); // JPanel.add(JCheckBox(name))
				// 添加到【面板 Panel】中
		}

		getContentPane().add(panel);
			// Pane n. 窗格,面板
			// 获取内容面板.add(JPanel(Menu + n个JCheckBox))

		return list; // return List<JCheckBox>
	}
}


/*
然后，我们设计一个【Mediator类】，【Mediator】引用【4个UI组件】，并负责【跟它们交互】： 

【Mediator类】: */
public class Mediator {
	// 引入【UI组件】
	private List<JCheckBox> checkBoxList; // JPanel.JCheckBox -> 复选框List
	private JButton selectAll; // JButton 
	private JButton selectNone; // JButton
	private JButton selectInverse; // JButton

	// Init
	public Mediator(List<JCheckBox> checkBoxList, JButton selectAll, JButton selectNone, JButton selectInverse) {
		this.checkBoxList = checkBoxList;
		this.selectAll = selectAll;
		this.selectNone = selectNone;
		this.selectInverse = selectInverse;

		// 绑定事件
		this.checkBoxList.forEach(checkBox -> {
			check.addChangeListener(this::onCheckBoxChanged);
		}); // this.checkBoxList.checkBox.addChangeListener(变化_调用的函数)

		this.selectAll.addActionListener(this::onSelectAllClicked);
		this.selectNone.addActionListener(this::onSelectNoneClicked);
		this.selectInverse.addActionListener(this::onSelectInverseClicked);
	}

	// 当checkbox有变化的时候
	public void onCheckBoxChanged(ChangeEvent event) {
		boolean allChecked = true; // 全部选中
		boolean allUnchecked = true; // 全部未选中
			// checked v. 选中 || adj. 选中的

		for (var checkBox : checkBoxList) {
			if (checkBox.isSelected()) {
				allUnchecked = false; // 选中了 = 全部未选中false
			} else {
				allChecked = false; // 未选中 = 全部选中false
			} /*
				交叉原理,
				 选中 -> 全部[未选] = false
				 未选 -> 全部[选中] = fasle
			*/
		}

		selectAll.setEnabled(!allChecked); // !全部选中
		selectNone.setEnabled(!allUnchecked); // !全部未选中
	}

	// 当点击select all的时候
	public void onSelectAllClicked(ActionEvent event) {
		checkBoxList.forEach(checkBox -> checkBox.setSelected(true));
		selectAll.setEnabled(false);
		selectNone.setEnabled(true);
	}

	// 当点击select none
	public void onSelectNoneClicked(ActionEvent event) {
		checkBoxList.forEach(checkBox -> checkBox.setSelected(false));
		selectAll.setEnabled(true);
		selectNone.setEnabled(false);
	}

	// 当点击select inverse
	public void onSelectInverseClicked(ActionEvent event) {
		checkBoxList.forEach(checkBox -> checkBox.setSelected(!checkBox.isSelected()));
		onCheckBoxChanged(null);
	}
}

/*
运行一下看看效果：
-----------------------------------------------------
|				Order 								|
-----------------------------------------------------
|	Use Mediator Pattern							|
|													|
|	Menu: O Hanburger  O Nugget  O Chip  O Coffee	|
|													|
|  Select All 	 Select None  	Inverse Select 		|
|													|
|													|
-----------------------------------------------------



使用【Mediator模式】后，我们得到了【以下好处】：

	· 各个【UI组件】互不引用，这样就减少了【组件之间的耦合关系】；
	· 【Mediator】用于【当一个组件发生状态变化时】，根据当前【所有组件的状态】决定更新【某些组件】；
	· 如果【新增一个UI组件】，我们只需要【修改Mediator更新状态的逻辑】，【现有的】其他UI组件【代码不变】。


【Mediator模式】经常用在有【众多交互组件的UI】上。


为了简化UI程序，【MVC模式】以及【MVVM模式】都可以看作是【中介 Mediator模式的扩展】。


================================================================


#	练习

使用Mediator模式  */



/*===============================================================


#	----- 中介 Mediator の 小结 -----

1. 中介模式是通过引入一个中介对象，把多边关系变成多个双边关系，从而简化系统组件的交互耦合度。

----------------

小总结: 
	
【Mediator类】 是 UI的【操作逻辑】归纳,

	(1) 【UI可视化部分】,编写规则如下:

		1. 设置 Titile、Size、默认关闭等 属性

		2. getContentPane() -> Container + 自定义Panel 布局

		3. getContentPane()中添加【各个UI元素】

		4. 对【各个UI元素】设置【Mediator 中介(规则)】

		5. setVisible(True); 设置UI可视化
	
---------------

	(2) 【Mediator】中主要有【3个部分】组成:

		1. UI各个组件, 也就是"变量", 又可以看为M - Module 模型

		2. Init各个组件, 并【添加监听 + 绑定事件】给【各个UI】
		 	this.UI组件.addChangeListener(触发事件)
		 	this.UI组件.addActionListener(触发事件)

		3. 编写【各个触发事件】内部逻辑,并将【监听】的改变,对其他【UI组件】造成的改变,同样写入【触发事件】当中。


-----------------

MVC中, M & C = Mediator 中介, V = UI



*/




















